// <!--
//  * 严肃声明：
//  * 开源版本请务必保留此注释头信息，若删除我方将保留所有法律责任追究！
//  * 可正常分享和学习源码，不得用于违法犯罪活动，违者必究！
//  * Copyright (c) 2022 APThink David唐 all rights reserved.
//  * 版权所有，侵权必究！
//  *
// -->
import { CommonTree } from "./CommonTree"
import { get, post } from "@/api"
import log from "loglevel"
import { type IOptionNode } from "@/contants"

const defaultIntervalSecond = 60 * 15 //15分钟

class _CacheData {
  _data: any
  _lastUpdateTime = 0
  _forceUpdate = false
  _intervalSecond = 0

  constructor(intervalSecond: number) {
    this._intervalSecond = intervalSecond ? intervalSecond : 0
  }

  updateInterval(v: number) {
    this._intervalSecond = v
  }

  needUpdate() {
    this._forceUpdate = true
  }

  get isTimeout() {
    return (
      this._forceUpdate ||
      (this._intervalSecond > 0 &&
        (new Date().getMilliseconds() - this._lastUpdateTime) > this._intervalSecond * 1000)
    )
  }

  get data() {
    return this._data
  }

  set data(v) {
    this._data = v
    this._lastUpdateTime = new Date().getMilliseconds()
  }
}

class CacheHelper {
  _data: Map<string, any>

  constructor() {
    this._data = new Map()
  }

  needUpdate(key: string) {
    const cb = this._data.get(key)
    cb && cb.needUpdate()
  }

  public getTableTree(key: string) {
    let cb = this._data.get(key)
    return new Promise((resolve) => {
      if (!cb || cb.isTimeout) {
        log.debug("=>get " + key + " from server")
        const url = "/" + key + "/simple"
        get(url).then((d) => {
          cb = new _CacheData(defaultIntervalSecond)
          cb.data = new CommonTree()
          cb.data.data = d
          this._data.set(key, cb)
          resolve(cb.data)
        })
      } else {
        log.debug("=>get " + key + "  from cache")
        resolve(cb.data)
      }
    })
  }

  // David：大多数页面都会缓存，而各页面显示字段本就不同，缓存意义不大
  // getField(key) {
  //   return new Promise((resolve, reject) => {
  //     let cb = this._data.get(key)
  //     if (!cb || cb.isTimeout) {
  //       if (!cb) {
  //         cb = new _CacheData(defaultIntervalSecond)
  //         this._data.set(key, cb)
  //       }
  //       ApiUtil.getField([key]).then(d => {
  //         cb.data = new Map()
  //         cb.data.set('userfields', d.get("userfields").get(key))
  //         cb.data.set('allfields', d.get('allfields').get(key))
  //         log.debug("=>get " + key + "  from server")
  //         resolve(cb.data)
  //       }).catch(e => {
  //         reject(e)
  //       })
  //     } else {
  //       log.debug("=>get " + key + "  from cache")
  //       resolve(cb.data)
  //     }
  //   })
  // }

  // public getSysParams() {
  //   const key = "sysparams"
  //   let cb = this._data.get(key)
  //   if (!cb || cb.isTimeout) {
  //     const result = await new Promise((resolve) => {
  //       post("/common/sysparam/category", {
  //         categories: ["Other", "Advance", "Public", "Schedule"],
  //       }).then((d: any) => {
  //         const params = new Map<string, string>()
  //         d.forEach((x: any) => {
  //           params.set(x.name, x.value)
  //         })
  //         cb = new _CacheData(defaultIntervalSecond)
  //         cb.data = params
  //         this._data.set(key, cb)
  //         log.debug("=>get sysparams from server")
  //         resolve(cb.data)
  //       })
  //     })
  //     return result
  //   } else {
  //     log.debug("=>get sysparams from cache")
  //     return cb.data
  //   }
  // }

  private getBasedataResult(data: any[], category: string | Array<string>) {
    if (category instanceof Array) {
      const result = new Map()
      category.forEach((x) => {
        const ds = data.filter((d) => {
          return d.category == x
        })
        result.set(x, ds)
      })
      return result
    } else {
      return data.filter((x) => {
        return x.category == category
      })
    }
  }
  public async getBasedatas(category: string | Array<string>) {
    const key = "basedata"
    let cb = this._data.get(key)
    if (!cb || cb.isTimeout) {
      log.debug("=>get basedata from server")
      const result = await new Promise((resolve) => {
        get("/basedata/all").then((d) => {
          cb = new _CacheData(defaultIntervalSecond)
          cb.data = d
          this._data.set(key, cb)
          resolve(this.getBasedataResult(cb.data, category))
        })
      })
      return result
    } else {
      log.debug("=>get basedata from cache")
      return this.getBasedataResult(cb.data, category)
    }
  }

  private getSysdataResult(datas: any[], category: string | Array<string>) {
    if (category instanceof Array) {
      const result = new Map<string, Array<IOptionNode>>()
      category.forEach(c => {
        const l = datas.filter(x => {
          return x.category == c
        }).map(x => {
          return { id: x.name, value: parseInt(x.value) } as IOptionNode
        })
        result.set(c, l)
      })
      return result
    } else {
      return datas.filter((x) => {
        return x.category == category
      }).map(x => {
        return { id: x.name, value: parseInt(x.value) } as IOptionNode
      })
    }
  }
  public async getSysdata(category: string | Array<string>) {
    const key = "sysdata"
    let cb = this._data.get(key)
    if (!cb || cb.isTimeout) {
      log.debug("=>get sysdata from server")
      const result = await new Promise((resolve) =>
        get("/systemdata").then((d) => {
          cb = new _CacheData(defaultIntervalSecond)
          cb.data = d
          this._data.set(key, cb)
          resolve(this.getSysdataResult(cb.data, category))
        })
      )
      return result
    } else {
      log.debug("=>get sysdata from cache")
      return this.getSysdataResult(cb.data, category)
    }
  }
}

const cache = new CacheHelper()

export { cache }
